#if defined(FS_TEXCOORD0) && defined(FS_TEXCOORD1)
	varying vec4 VertexTexCoordVS;
#else
	#ifdef defined(FS_TEXCOORD0) || defined(FS_TEXCOORD1)
		varying vec2 VertexTexCoordVS;
	#endif
#endif

#if defined(FS_REFLECTION) || defined(FS_LIGHTING) || defined(FS_DOF)
	varying vec3 VertexPositionVS;
#endif

#ifdef FS_NORMAL
	varying vec3 VertexNormalVS;
	#ifdef FS_TANGENT_BINORMAL
		varying vec3 VertexTangentVS;
		varying vec3 VertexBinormalVS;
		#ifdef FS_PARALLAXMAPPING
			varying vec3 EyeVecVS;
		#endif
	#endif
#endif

uniform vec3 AmbientColor;
uniform vec4 DiffuseColor;

#ifdef FS_DIFFUSEMAP
	uniform sampler2D DiffuseMap;
	#ifdef FS_ALPHATEST
		uniform float AlphaReference;
	#endif
#endif

#ifdef FS_DIFFUSERAMPMAP
	uniform sampler1D DiffuseRampMap;
#endif

#ifdef FS_AMBIENTOCCLUSIONMAP
	uniform sampler2D AmbientOcclusionMap;
	uniform float AmbientOcclusionFactor;
#endif

#ifdef FS_LIGHTMAP
	uniform sampler2D LightMap;
	uniform vec3 LightMapColor;
#endif

#ifdef FS_EMISSIVEMAP
	uniform sampler2D EmissiveMap;
	uniform vec3 EmissiveMapColor;
#endif

#ifdef FS_REFLECTION
	uniform vec3 ReflectionColor;
	uniform float Reflectivity;
	#ifdef FS_REFLECTIVITYMAP
		uniform sampler2D ReflectivityMap;
	#endif
	#ifdef FS_FRESNELREFLECTION
		uniform vec2 FresnelConstants;
	#endif
	#ifdef FS_2DREFLECTIONMAP
		uniform sampler2D ReflectionMap;
		uniform mat3 ViewSpaceToWorldSpace;
	#elif defined(FS_CUBEREFLECTIONMAP)
		uniform samplerCube ReflectionMap;
		uniform mat3 ViewSpaceToWorldSpace;
	#endif
#endif

#ifdef FS_NORMALMAP
	uniform sampler2D NormalMap;
	uniform float NormalMapBumpiness;
	#ifdef FS_DETAILNORMALMAP
		uniform sampler2D DetailNormalMap;
		uniform float DetailNormalMapBumpiness;
		uniform vec2 DetailNormalMapUVScale;
	#endif
#endif

#ifdef FS_PARALLAXMAPPING
	uniform sampler2D HeightMap;
	uniform vec2 ParallaxScaleBias;
#endif

#ifdef FS_LIGHTING
	uniform vec3 LightDirection;		/** View space light direction */
	uniform vec3 LightColor;
	#ifdef FS_SPECULAR
		uniform vec3 SpecularColor;
		uniform float SpecularExponent;
		#ifdef FS_SPECULARMAP
			uniform sampler2D SpecularMap;
		#endif
		#ifdef FS_SPECULARRAMPMAP
			uniform sampler1D SpecularRampMap;
		#endif
	#endif
	#ifdef FS_EDGERAMPMAP
		uniform sampler1D EdgeRampMap;
	#endif
#endif

#ifdef FS_GLOW
	uniform float Glow;
	#ifdef FS_GLOWMAP
		uniform sampler2D GlowMap;
	#endif
#endif

#ifdef FS_DOF
	uniform vec4 DOFParams;
#endif

#ifdef FS_FRESNELREFLECTION
	float fresnel(vec3 light, vec3 normal, vec2 constants)
	{
		
	}
#endif

#ifdef FS_LIGHTING
	vec3 BlinnPhong(
	vec3 lightVector, 
	vec3 lightColor, 
	vec3 viewVecotr, 
	vec3 normalVector, 
	vec3 diffuseColor, 
	vec3 specularColor,
	float specularExponent)
	{
		float diffuse = clamp(dot(lightVector, normalVector), 0.0, 1.0);
		diffuse *= texture1D(DiffuseRampMap, diffuse);
		
		vec3 diffuseLighting = diffuse * diffuseColor * lightColor;
		#ifdef FS_SPECULAR
			vec3 halfVector = normalize(lightVector + viewVecotr);
			float specular = pow(clamp(dot(halfVector, normalVector), 0.0, 1.0), specularExponent);
			vec3 specularLighting = specular * specularColor * lightColor;
			#ifdef FS_SPECULARRAMPMAP
				specularLighting *= texture1D(SpecularRampMap, specular).x;
			#endif
		#endif
	}
#endif

void main()
{
	#if defined(FS_TEXCOORD0) && defined(FS_TEXCOORD1)
		vec2 TexCoord0 = VertexTexCoordVS.xy;
		#define TexCoord1 VertexTexCoordVS.zw;
	#else
		#ifdef FS_TEXCOORD0
			vec2 TexCoord0 = VertexTexCoordVS;
		#endif
		
		#ifdef FS_TEXCOORD1
			#define TexCoord1 VertexTexCoordVS
		#endif
	#endif
	
	#ifdef FS_PARALLAXMAPPING
		vec3 eyeVec = normalize(EyeVecVS);
		float scale = ParallaxScaleBias.x;
		float bias = ParallaxScaleBias.y;
		float height = texture2D(HeightMap, TexCoord0).r;
		
		float offset = height * scale + bias;
		vec2 textureCoordinate = TexCoord0 + offset * eyeVec.xy;
		
		float height2 = height + texture2D(HeightMap, textureCoordinate).r * 0.5;
		
		offset = height2 * scale + bias;
		
		TexCoord0 = TexCoord0 + offset * eyeVec.xy;
	#endif
	
	#ifdef FS_AMBIENTOCCLUSIONMAP
		vec3 ambientColor = AmbientColor * (texture2D(AmbientOcclusionMap, TexCoord1).r * AmbientOcclusionFactor);
	#else
		#define ambientColor AmbientColor
	#endif
	
	#ifdef FS_LIGHTMAP
		vec3 lightMapColor = texture2D(LightMap, TexCoord1).rgb;
		#ifdef FS_GAMMACORRECTION
			lightMapColor = pow(lightMapColor, vec3(2.2, 2.2, 2.2));
		#endif
		
		lightMapColor *= LightMapColor;
	#else
		#define lightMapColor vec3(0.0, 0.0, 0.0)
	#endif
	
	#ifdef FS_EMISSIVEMAP
		vec3 emissiveColor = texture2D(EmissiveMap, TexCoord0).rgb;
		#ifdef FS_GAMMACORRECTION
			emissiveColor = pow(emissiveColor, vec3(2.2, 2.2, 2.2));
		#endif
		
		emissiveColor *= EmissiveMapColor;
	#else
		#define emissiveColor vec3(0.0, 0.0, 0.0)
	#endif
	
	#ifdef FS_DIFFUSEMAP
		 vec4 diffuseMapTexel = texture2D(DiffuseMap, TexCoord0);
		 #ifdef FS_ALPHATEST
			if (diffuseMapTexel.a < AlphaReference) discard;
		 #endif
		 
		#ifdef FS_GAMMACORRECTION
			diffuseMapTexel.rgb = pow(diffuseMapTexel.rgb, vec3(2.2, 2.2, 2.2));
		#endif
		
		vec3 diffuseColor = diffuseMapTexel.rgb * DiffuseColor.rgb;
	#else
		vec3 diffuseColor = DiffuseColor.rgb;
	#endif
	
	#ifdef FS_NORMAL
		#ifdef FS_NORMALMAP
			vec3 normal = texture2D(NormalMap, TexCoord0).xyz * 2.0 - 1.0;
			normal.xy *= NormalMapBumpiness;
			
			vec3 detailNormal = vec3(0.0, 0.0, 0.0);
			#ifdef FS_DETAILNORMALMAP
				detailNormal = texture2D(DetailNormalMap, TexCoord0 * DetailNormalMapUVScale).xyz * 2.0 - 1.0;
			#endif
			normal = normal + detailNormal * DetailNormalMapBumpiness;
			
			/** transform normal to view. */
			normal = normalize(normal.x * VertexTangentVS + normal.y * VertexBinormalVS + normal.z * VertexNormalVS);
		#endif
	#endif
	
	#ifdef FS_REFLECTION
		float reflectivity = Reflectivity;
		#ifdef FS_FRESNELREFLECTION
			reflectivity *= fresnel(normalize(-VertexPositionVS), normal, FresnelConstants);
		#endif
	#endif
	
	#ifdef FS_LIGHTING
		#ifdef FS_SPECULARMAP
			vec4 specularMapTexel = texture2D(SpecularMap, TexCoord0);
			vec3 specularColor = specularMapTexel.rgb * SpecularColor;
			float specularExponent = specularMapTexel.a * SpecularExponent;
		#else
			#define specularColor vec3(0.0, 0.0, 0.0)
			#define #define specularExponent 0.0
		#endif
		
		vec3 lightingColor = BlinnPhong(LightDirection, LightColor, normalize(-VertexPositionVS), normal, diffuseColor, specularColor, specularExponent);
	#else
		#define lightingColor 0.0
	#endif
	
	float alphaValue = DiffuseColor.a;
	
	#ifdef FS_GLOW
		#ifdef FS_GLOWMAP
			alphaValue = 1.0 - ((1.0 - Glow) * texture2D(GlowMap, TexCoord0)).r;
		#endif
	#endif
	
	#ifdef FS_DOF
		float f = -VertexPositionVS.z;
		
		if (f < DOFParams.y)
		{
			
		}
	#endif
}